/// <reference path="base.ts" />
/// <reference path="helpers.ts" />
/// <reference path="quadrant.d.ts" />

class QuadrantPage extends Base.Page {
    private stickTemplate: HandlebarsTemplateDelegate;
    private newStick: Stick = null;

    public Ready(): void {
        super.Ready();
        this.stickTemplate = Handlebars.compile($("#stick-template").html());

        BaseHelpers.AjaxService("GET",
            this.options.urlZones, null,
            (data) => {
                if (data) {
                    this.SetZones(data);
                } else {
                    toastr.error("No defined zone");
                }
            });
        BaseHelpers.AjaxService("GET",
            this.options.urlStick, null,
            (data) => {
                if (data) {
                    this.SetSticks(data);
                } else {
                    toastr.error("No stick found");
                }
            }).then(() => {
                this.SetDragDrop($("div[draggable='true']"));
            });
    }

    private SetDragDrop(elements: JQuery): void {
        elements.on('dragstart', function (e: JQueryEventObject) {
            var offset = $(e.currentTarget).offset(),
                event: any = e.originalEvent,
                offset_data = (offset.left - event.clientX) + ';' + (offset.top - event.clientY);
            e.originalEvent.dataTransfer.setData('Text', this.id + ";" + offset_data);
            e.originalEvent.dataTransfer.effectAllowed = "move";
            return true;
        });
        $("#stick-container").unbind("drop").unbind("dragover")
            .on('drop', (e: JQueryEventObject) => {
                var event: any = e.originalEvent;
                //event.stopPropagation && event.stopPropagation();
                var zoneElement: JQuery = $(e.target);
                var data = event.dataTransfer.getData("Text").split(";");
                this.DropStick(data[0], zoneElement, {
                    top: event.clientY + parseInt(data[2]),//-event.offsetY,
                    left: event.clientX + parseInt(data[1])
                });

                return false;
            })
            .on("dragover", (event: JQueryEventObject) => {
                event.originalEvent.dataTransfer.dropEffect = "move";
                event.preventDefault && event.preventDefault();
                return false;

            });
    }

    private DropStick(id: string, zoneElement: JQuery, position: JQueryCoordinates) {
        var element: JQuery = $("#" + id),
            parentZone: JQuery = $("#stick-container"),
            parentOffset: JQueryCoordinates = parentZone.offset(),
            ratioX: number = Math.round((((position.left - parentOffset.left) / parentZone.width()) * 100) * 10000) / 10000,
            ratioY: number = Math.round((((position.top - parentOffset.top) / parentZone.height()) * 100) * 10000) / 10000,
            //zone: number = parseInt(zoneElement.attr("id").substr(1)),
            name: string = element.find(".namecontent").first().text(),
            //comments: string = element.find(".commentscontent").first().text(),
            stickId: number = parseInt(id.substring(5)),
            stposition: BoardPosition = {
                X: ratioX,
                Y: ratioY,
                Zone: 0 //zone
            };
        element.removeAttr("style").offset(position);

        BaseHelpers.AjaxService("PUT",
            this.options.urlStick + stickId,
            stposition,
            (data: boolean) => {
                if (data == true) {
                    toastr.success(name + " Saved");
                } else {
                    toastr.error("No stick found");
                }
            });

    }

    private SetSticks(sticks: Array<Stick>): void {
        var xPos: number = 0, yPos: number = 18;

        sticks.forEach((stick: Stick) => {
            if (stick.Position.X == 0 && stick.Position.Y == 0) {
                // If stick is not postionned, cascade it
                stick.Position.X = xPos;
                stick.Position.Y = yPos;
                xPos += 5;
                yPos += 5;
            }
            $("#stick-container").append(this.stickTemplate(stick));
        });

        $("#btn-delete-stick").click((e: JQueryEventObject) => {
            var id: string = $(e.currentTarget).attr("data-id");
            BaseHelpers.AjaxService("DELETE", this.options.urlStick + id, null,
                (data) => {
                    if (data) {
                        toastr.success("Sticker deleted");
                        $("#wrap-" + id).remove();
                    }
                }).always($('#delete-sticker').modal('hide'));
        });

        this.SetSticksActions();
        this.SetFormForStick();
    }

    private SetSticksActions(): void {
        $("a.t-stick-edit").unbind("click").click((e: JQueryEventObject) => {
            e.preventDefault();
            var id: string = $(e.currentTarget).attr("data-id");
            this.GetFormData(id, this.options.urlStick, "#update-stick", "Unable to read this sticker");
            $('#update-stick').modal('show');
        });
        $("a.t-stick-del").unbind("click").click((e: JQueryEventObject) => {
            e.preventDefault();
            var id: string = $(e.currentTarget).attr("data-id");
            $("#btn-delete-stick").attr("data-id", id);
            $('#delete-sticker').modal('show');
        });
    }

    private SetFormForStick(successCallBack?: any): void {
        this.SetForm(this.options.urlStick, "#formstick", '#update-stick',
            "btn-save-stick", "Id", ["QuadrantId", "Name", "Comments"], "#st-",
            "sticker successfull updated", (result: OpResult) => {
                if (this.newStick != null) {
                    this.newStick.Id = parseInt(result.Id);
                    $("#stick-container").append(this.stickTemplate(this.newStick));
                    this.SetDragDrop($("#wrap-" + result.Id));
                    this.SetSticksActions();
                    this.newStick = null;
                }
            });
    }

    private SetZones(zones: Array<any>): void {
        zones.forEach((zone) => {
            $("#zh-Name" + zone.BoardZone).html(zone.Name);
            $("#za" + zone.BoardZone).attr("data-id", zone.Id)
                .attr("data-toggle", "modal")
                .attr("data-target", "#update-zone");
            $("#zl" + zone.BoardZone).text(zone.Legend);
        });

        this.SetForm(this.options.urlZones, "#formzone", '#update-zone',
            "btn-save-zone", "BoardZone", ["Name"], "#zh-",
            "Zone successfull updated");

        $("#add-stick").click(() => {
            this.AddSticker();
        });

        $('#update-zone')
            .on('show.bs.modal', (e: any) => {
                var zoneId: string = $(e.relatedTarget).attr("data-id");
                this.GetFormData(zoneId, this.options.urlZones, "#update-zone", "Unable to read this zone definition");
            });
    }

    private AddSticker(): void {
        this.newStick = {
            Name: "New sticker",
            Id: null,
            QuadrantId: this.options.id,
            Comments: "",
            Position: {
                X: 5,
                Y: 5,
                Zone: 0
            }
        };
        this.InjectFormData(this.newStick, "#update-stick");
        $('#update-stick').modal('show');
    }

    private SetForm(url: string, formName: string, modalName: string, buttonName: string,
        propId: string, props: Array<any>, refreshPrefix: string, successMessage: string,
        successCallBack?: any): void {

        $(formName).submit(function () {
            if ($(this).valid()) {
                var btn: JQuery = $(buttonName);
                btn.button('loading');
                var refreshId: string = $(this[propId]).val();
                var aRefresh: Array<any> = new Array();
                for (var prop in props) {
                    var value: string = $(this[props[prop]]).val();
                    aRefresh.push([props[prop], value]);
                }

                $.ajax({
                    url: url,
                    type: this.method,
                    data: $(this).serialize(),
                    success: (result: OpResult) => {
                        if (result && result.Success == true) {
                            toastr.success(successMessage);
                            successCallBack && successCallBack(result);
                            if (!refreshId) refreshId = result.Id;
                            for (var refresh in aRefresh) {
                                $(refreshPrefix + aRefresh[refresh][0] + refreshId).text(aRefresh[refresh][1]);
                            }
                            this.reset();
                            $(modalName).modal('hide');
                        }
                    }
                }).always(btn.button('reset'));
            }
            return false;
        });
    }

    private GetFormData(id: string, url: string, modalName: string, errorMessage: string): JQueryXHR {
        return BaseHelpers.AjaxService("GET", url, { id: id },
            (data) => {
                if (data) {
                    this.InjectFormData(data, modalName);
                } else {
                    toastr.error(errorMessage);
                }
            });
    }

    private InjectFormData(data: any, modalName: string): void {
        var children: JQuery = $(modalName).children();
        for (var propertyName in data) {
            children.find("#" + propertyName).val(data[propertyName]);
        }
    }
}                               